You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This branch is not a small project-config patch. It changes Gecko from a relatively flat config and vector service into a multi-surface backend that now owns:
typed project configuration records
project-oriented config CRUD routes
Git-backed project repository state and read APIs
GitHub/Fence integration points for installation and token brokering
organization-level Git connect/reconcile flows
upload session persistence and PR-oriented file submission flows
thumbnail storage for projects
a full internal package reorganization
CI and runtime changes required by the new Git subsystem
The branch is large because it combines feature delivery with a substantial internal re-layout. The biggest review question is not any one handler. It is whether the new package boundaries, auth model, data model, and route surface still line up cleanly with the CALYPR frontend and deployment stack.
Scope by Area
git diff --dirstat against main shows the branch is concentrated in these areas:
internal/git/ ~10%
internal/server/http/git/ ~9%
internal/server/middleware/ ~8%
gecko/ legacy removal/replacement ~8%
internal/server/http/config/ ~7%
internal/db/ ~6%
config/ ~5%
internal/thumbnail/ ~5%
tests/integration/ ~4%
That matches the real shape of the work: this is mostly a Git/project backend branch, plus the refactor needed to support it.
Architecture Reorganization
Before
The old service logic lived mostly in the top-level gecko/ package with mixed concerns:
HTTP handlers
middleware
DB logic
vector logic
config logic
response helpers
After
The branch moves Gecko toward a clearer package layout:
This is the right direction structurally. The tradeoff is that the branch mixes architectural reorganization with product behavior changes, so code review needs to separate “moved” from “changed.”
Runtime / Bootstrap Changes
main.go now builds Gecko as a composable server with optional integrations:
PostgreSQL
Git service
thumbnail store
Qdrant
Grip
JWKS-backed JWT validation
The important runtime additions are:
--git-data-dir / GIT_DATA_DIR
--fence-base-url / FENCE_BASE_URL
--github-api-base-url / GITHUB_API_BASE_URL
Once DB connectivity is available, Gecko now also constructs:
git.NewGitService(...)
thumbnail.NewFilesystemStore(gitDataDir)
That makes gitDataDir a hard runtime dependency for the Git-enabled server path.
CI impact
Because Gecko now requires a Git data directory, CI had to be updated. The branch modifies:
.github/workflows/tests.yaml
to launch Gecko with:
-git-data-dir /tmp/gecko-git
Without that, the service exits before health checks come up.
Config Model Changes
Project config becomes first-class
This branch adds a typed ProjectConfig model in:
config/projectConfig.go
Supported fields:
title
contact_email
src_repo
org_title
description
project_title
Validation includes:
required-field checks
email validation
repository URL normalization into a GitHub-style host/owner/repo form
This is a real shift from using generic config blobs everywhere. Project metadata now has a stronger contract and normalization behavior.
Explorer config compatibility
This branch also carries forward explorer config compatibility work, including the richer fileActions shape:
That matters because the frontend expects this richer form, and Gecko has to unmarshal it correctly for CALYPR configs to load.
Database / Persistence Changes
The database layer is no longer only about simple config_schema.<type> JSON tables.
Existing typed config tables
The init path now ensures config tables for:
explorer
nav
file_summary
project
projects
New Git-related state tables
internal/db/EnsureGitProjectStateTable expands the DB footprint significantly. This branch adds persistence for:
config_schema.git_project_state
repository identity
installation metadata
mirror path
sync/default branch/error state
config_schema.git_organization_state
organization installation/configuration status
target metadata
timestamps and last error
config_schema.git_upload_session
upload/PR submission session metadata
config_schema.git_upload_session_file
per-file status inside an upload session
config_schema.git_pending_repository
repositories discovered but not yet reconciled into project config
supports both webhook-originated and user-scoped pending records
config_schema.git_setup_session
setup snapshot used to compare repository sets before/after install/connect flows
This is one of the biggest branch changes. Gecko is no longer stateless around Git operations; it is now persisting lifecycle and reconciliation state explicitly.
HTTP Surface Changes
The route surface is much broader than before.
Top-level registration
The new entrypoint is:
internal/server/http/register.go
Registered route families:
/health
/Dir...
/config...
/git...
vector routes
swagger JSON route
Config routes
internal/server/http/config/register.go now exposes:
Generic config routes
GET /config/types
GET /config/list
Typed config groups:
/config/explorer
/config/nav
/config/file_summary
/config/project
Per-type operations include combinations of:
GET /list
GET /:configId
PUT /:configId
DELETE /:configId
Project config routes
This branch adds a dedicated project config surface:
GET /config/projects
GET /config/projects/list
GET /config/projects/summary
GET /config/projects/:orgTitle/:projectTitle
PUT /config/projects/:orgTitle/:projectTitle
DELETE /config/projects/:orgTitle/:projectTitle
DELETE /config/projects/:orgTitle
This is materially different from the old “config row by arbitrary key” model. The route shape now matches organization/project semantics directly.
Git routes
internal/server/http/git/register.go is one of the largest new route families in the service.
Organization-level Git routes
GET /git/projects
GET /git/organizations/status
POST /git/organizations/reconcile
POST /git/organizations/:orgTitle/init-connect
POST /git/organizations/:orgTitle/connect
GET /git/organizations/:orgTitle/status
POST /git/organizations/:orgTitle/reconcile
These routes cover installation status, connect flows, and organization-wide repository reconciliation.
Project-level Git read routes
GET /git/projects/:orgTitle/:projectTitle
GET /git/projects/:orgTitle/:projectTitle/refs
GET /git/projects/:orgTitle/:projectTitle/tree
GET /git/projects/:orgTitle/:projectTitle/tree/*
GET /git/projects/:orgTitle/:projectTitle/file/*
GET /git/projects/:orgTitle/:projectTitle/download/*
GET /git/projects/:orgTitle/:projectTitle/thumbnail
These expose Gecko as a repository-backed project read service, not just a config API.
Project-level Git write/workflow routes
PUT /git/projects/:orgTitle/:projectTitle/setup
PUT /git/projects/:orgTitle/:projectTitle/storage
PUT /git/projects/:orgTitle/:projectTitle/thumbnail
POST /git/projects/:orgTitle/:projectTitle/uploads/session
GET /git/projects/:orgTitle/:projectTitle/uploads/session/:sessionID
POST /git/projects/:orgTitle/:projectTitle/uploads/session/:sessionID/files
POST /git/projects/:orgTitle/:projectTitle/uploads/session/:sessionID/finalize
This is a major expansion of product surface. Gecko is now responsible for project repository setup, update, artifact flow staging, and PR-style finalization.
Auth and Access Model
The middleware layer has been significantly expanded.
Resource path model
The branch standardizes project authorization around Arborist-style paths:
/programs/{organization}/projects/{project}
Helper functions in internal/server/middleware/access.go normalize and check these resource paths.
Config auth model
ConfigAuth now treats explorer configs differently from base/global config routes:
and also allows certain broader admin-like resource paths such as:
*
/programs
/programs/{org}
/programs/{org}/projects
Git auth model
Git reads and organization reads are protected separately:
GitProjectAuth
GitOrganizationAuth
The important boundary in this branch is:
caller authorization still comes from the request Authorization token and Arborist/Fence checks
Git remote access is not the same thing as caller auth and is handled separately through the Git integration flow
That split is correct, but reviewers should confirm it stays consistent across all write routes.
Fence / GitHub Integration Model
This branch adds explicit integration clients instead of spreading ad hoc HTTP logic through handlers.
Fence integration
internal/integrations/fence/client.go turns Fence into a GitHub App broker that Gecko calls for:
install URL requests
organization installation status
repository installation status
installation repository listing
installation token minting
The request target is:
POST {FENCE_BASE_URL}/credentials/github
with action-based payloads.
This is architecturally important. Gecko is moving away from owning GitHub App secrets directly and toward asking Fence for short-lived GitHub access on demand.
GitHub integration
internal/integrations/github/client.go uses:
github.com/google/go-github/v87/github
for GitHub API metadata reads.
At minimum, it currently centralizes repository metadata lookup:
default branch
HTML URL
This is the right direction and avoids more hand-written GitHub REST client code.
Git Service and Repository Semantics
The branch adds a large internal/git/ package that now owns:
repository identity/domain types
setup and reconcile flows
repository state persistence coordination
update/sync operations
upload workflows
response shaping
error mapping
The key product shift is that Gecko is no longer just proxying config or metadata. It now maintains local repository state under a configured data directory and serves project Git views from there.
Reviewers should pay special attention to:
when local repository state is created
how update behaves when the local repo is missing vs already present
how default branch information is sourced and persisted
where Fence tokens are requested and how long they are retained in memory
Upload and Thumbnail Workflows
Two entirely new concerns land in this branch.
Upload sessions
Upload state is now explicit and persistent:
session creation
file list replacement/storage
session lookup
finalize flow
PR metadata persistence
This means Gecko now participates in a staged contribution workflow rather than just reading repository state.
Thumbnails
internal/thumbnail/ adds filesystem-backed thumbnail storage plus validation.
Route support includes:
GET /git/projects/:orgTitle/:projectTitle/thumbnail
PUT /git/projects/:orgTitle/:projectTitle/thumbnail
That is a durable product-surface change and should be reviewed as such, not as a minor helper addition.
Legacy Code Removal
A large part of the diff is deletion of the old flat handlers from gecko/, including legacy files such as:
handleConfig.go
handleDir.go
handleVector.go
middleware.go
response.go
server.go
This is not dead-code cleanup alone. These deletions are paired with replacements under internal/server/http/..., internal/server/middleware/..., and supporting packages.
Build / Tooling Changes
This branch also touches:
Dockerfile
Makefile
.dockerignore
go.mod
go.sum
swagger/docs artifacts
Those are not side noise. They are part of the fallout from:
root build compatibility
package reorganization
new GitHub client dependency
swagger generation drift
Review should include a sanity pass on container build assumptions and root go build . behavior.
Testing Changes
The branch adds or updates tests across multiple layers:
config tests
project config tests
middleware tests
Git service tests
upload tests
Fence integration tests
thumbnail tests
integration tests
Notable files include:
config/explorerConfig_test.go
config/projectConfig_test.go
internal/git/service_test.go
internal/git/upload_test.go
internal/integrations/fence/client_test.go
internal/server/middleware/git_test.go
internal/thumbnail/store_test.go
tests/integration/*
Given the branch size, the main review question is coverage shape rather than raw test count:
do route tests reflect current auth semantics?
do config tests lock frontend/backend schema compatibility?
do Git tests cover first-time setup, update, and persistence transitions?
Highest-Risk Areas
If reviewing this branch for merge readiness, focus here first:
Auth correctness
project vs organization vs generic config auth
read vs write route consistency
Route compatibility
does the route surface still match the frontend and revproxy expectations?
DB/state lifecycle
are new tables initialized everywhere Gecko runs?
are deletes/updates cleaning up related Git state correctly?
Git/Fence boundary
does Gecko request the right thing from Fence?
is Gecko still assuming too much GitHub App behavior locally?
Config schema compatibility
especially explorer config and project config alignment with the frontend
Startup behavior
new hard dependency on git-data-dir
optional integrations degrading cleanly when unset
Bottom Line
This branch should be read as a backend expansion and service re-platforming branch, not as a narrow project-config feature.
The durable outcomes are:
Gecko now has a first-class project config model.
Gecko now has a real Git-backed project API surface.
Gecko now persists Git lifecycle state instead of treating repo operations as transient.
Gecko now relies on Fence as the GitHub App broker boundary.
Gecko’s internal organization is materially better, but the branch is broad enough that compatibility review has to be disciplined.
This PR is already merged (merged 21 hours ago). The review is post-facto,
Overview
106 files changed, +10,939 additions, -2,809 deletions across 46 commits
The PR combines three major initiatives:
Fiber v3 migration (HTTP framework)
Project configuration as a first-class concern (typed config model)
Git-backed project API surface (repository management, uploads, reconciliation)
This is NOT a small feature patch. It's a fundamental restructuring of Gecko's architecture.
Assessment Against Your Focus Areas
1. Auth Correctness⚠️ CRITICAL REVIEW AREAS
Status: Implemented but needs verification
Key changes:
New Arborist-style resource path model: /programs/{org}/projects/{project}
Distinct auth models:
ConfigAuth: Project-scoped for explorer configs; broad read access for others; write/delete requires route-specific auth
ProjectConfigAuth: Direct access check + fallback to broader paths (*, /programs, /programs/{org}, /programs/{org}/projects)
GitProjectAuth & GitOrganizationAuth: Separate authorization layers
Potential gaps:
✓ Read vs write route consistency: Explorer vs. non-explorer config split is clear
⚠️Caller auth vs Git remote auth boundary: The split between request authorization (Arborist/Fence) and Git remote access (handled separately) must stay consistent across all write routes. Check:
Status: Significantly expanded; must verify frontend/revproxy expectations
New route surface is now:
Config routes (new structure):
GET /config/types → list known types
GET /config/list → list all configs (generic)
GET /config/projects → new dedicated project endpoint
GET /config/projects/list → project list
GET /config/projects/summary → project summary
GET /config/projects/:orgTitle/:projectTitle
PUT /config/projects/:orgTitle/:projectTitle
DELETE /config/projects/:orgTitle/:projectTitle
DELETE /config/projects/:orgTitle → cascade delete org projects
Git routes (entirely new):
Organization-level:
GET /git/projects
GET /git/organizations/status
POST /git/organizations/reconcile
POST /git/organizations/:orgTitle/init-connect
POST /git/organizations/:orgTitle/connect
GET /git/organizations/:orgTitle/status
POST /git/organizations/:orgTitle/reconcile
Project-level (read):
GET /git/projects/:orgTitle/:projectTitle
GET /git/projects/:orgTitle/:projectTitle/refs
GET /git/projects/:orgTitle/:projectTitle/tree
GET /git/projects/:orgTitle/:projectTitle/tree/*
GET /git/projects/:orgTitle/:projectTitle/file/*
GET /git/projects/:orgTitle/:projectTitle/download/*
GET /git/projects/:orgTitle/:projectTitle/thumbnail
Project-level (write/workflow):
PUT /git/projects/:orgTitle/:projectTitle/setup
PUT /git/projects/:orgTitle/:projectTitle/storage
PUT /git/projects/:orgTitle/:projectTitle/thumbnail
DELETE /git/projects/:orgTitle/:projectTitle/thumbnail
POST /git/projects/:orgTitle/:projectTitle/update
POST /git/projects/:orgTitle/:projectTitle/uploads/session
GET /git/projects/:orgTitle/:projectTitle/uploads/session/:sessionID
POST /git/projects/:orgTitle/:projectTitle/uploads/session/:sessionID/files
POST /git/projects/:orgTitle/:projectTitle/uploads/session/:sessionID/finalize
ISSUE: No frontend/revproxy expectations documented in this review. Verify with frontend team that these routes match their expectations.
3. DB/State Lifecycle⚠️ CRITICAL
Status: New persistent state model; must verify initialization everywhere
New tables created:
config_schema.git_project_state → repository identity, install metadata, mirror path, sync state
config_schema.git_organization_state → org installation/config status, target metadata, timestamps
config_schema.git_upload_session → upload/PR submission session metadata
config_schema.git_upload_session_file → per-file status inside upload session
config_schema.git_pending_repository → repositories discovered but not yet reconciled
config_schema.git_setup_session → setup snapshot for comparing repo sets before/after
Critical questions (may not be fully answered in code):
✓ Initialization: internal/db/EnsureGitProjectStateTable() is called, but is it called in all deployment contexts (CI, helm, dev)?
See .github/workflows/tests.yaml: CI now passes -git-data-dir /tmp/gecko-git ✓
But: Verify helm/production init logic
✓ Delete/cascade: Does deleting a project/org cascade cleanup of:
corresponding git_project_state rows?
corresponding git_upload_session* rows?
Not explicitly shown in code review. Check internal/server/http/git/* delete handlers.
⚠️Git state orphaning: What if a git_project_state row exists but the local mirror directory is missing? Recovery logic?
4. Git/Fence Boundary⚠️ CRITICAL DEPENDENCY
Status: Explicit integration model introduced; significant behavior change
New model:
Gecko no longer owns GitHub App secrets directly
Gecko calls Fence for:
Install URL requests → POST {FENCE_BASE_URL}/credentials/github with action-based payloads
Organization installation status
Repository installation status
Installation repository listing
Installation token minting (short-lived tokens on demand)
Critical dependencies:
FENCE_BASE_URL is now required at runtime (no fallback shown)
See main.go startup: Need to verify this is hard-failed if missing, not silently skipped
Fence token lifetime & caching: Where are tokens cached in memory? How long? Refresh strategy?
This is a behavioral change from previous local GitHub App handling
Risk: Token expiration during long-running operations (e.g., large git clone)
How does Gecko stay in sync with Fence?
✓ Initial reconciliation: /git/organizations/:orgTitle/reconcile calls Fence to list repos
✓ User-initiated: Setup/connect flows pull fresh state from Fence
⚠️Webhook-driven: Does Gecko receive webhooks when Fence detects new GitHub App installations? Not shown in code. If not:
Gecko may have stale git_organization_state until next manual reconcile
Users may be confused about why new repos don't appear
Status: New hard dependency introduced; optional integrations may not degrade cleanly
Hard dependency:
--git-data-dir / GIT_DATA_DIR is now required for the Git service path
Without it, Gecko exits before health checks (no graceful degradation)
Updated in CI: .github/workflows/tests.yaml now passes -git-data-dir /tmp/gecko-git ✓
Optional integrations (graceful degradation):
--qdrant-* → Skips Qdrant endpoints if not provided ✓
--grip-* → Skips Grip endpoints if not provided ✓
--db → Skips DB endpoints if not provided (warning logged) ✓
Question: What if --git-data-dir points to a non-existent or non-writable directory?
Not clear from code. Check internal/git/service.go initialization.
Dockerfile & Container changes:
Updated to golang:1.26.3-alpine3.22 (was 1.24.2)
Multi-stage build now uses BuildKit syntax (syntax=docker/dockerfile:1.7)
Runs as non-root user gecko ✓
Copies docs/swagger.json into image ✓
High-Risk Code Patterns
Cascade delete logic: /config/projects/:orgTitle deletes all projects in an org. Verify related state (git_project_state, git_upload_session) is cleaned up.*
Token lifecycle: Fence integration caches tokens in memory. What's the TTL? Refresh strategy on expiration?
Repository mirror management: Local git mirrors stored under git-data-dir. What's the cleanup strategy? Orphaned mirrors? Disk space limits?
Upload session finalization: Needs to atomically:
Commit staged files to git
Create PR via Fence/GitHub
Update session state
Verify transaction boundaries.
Suggestions for Post-Merge Validation
E2E test: Walk through full project setup → file upload → PR creation workflow with Fence integration
Migration plan: Document how existing project configs (if any) migrate to new typed model
Fence contract: Sync with Fence team on token lifecycle, webhook notifications, rate limits
✓ Merged successfully. The branch is architecturally sound but introduces significant behavioral changes:
Auth model is more explicit but requires consistency verification across all routes
Route surface is much broader (Git operations are now a first-class Gecko concern, not delegated)
State is no longer ephemeral; new persistence requirements across all deployments
Fence is now a hard dependency for Git operations; token lifecycle needs care
Startup has a new hard requirement (git-data-dir)
The code is well-organized and testable, but integration with frontend, Fence, and operational procedures needs explicit sign-off before this is production-ready.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
PR Notes:
feature/project-configWhat This Branch Actually Does
This branch is not a small project-config patch. It changes Gecko from a relatively flat config and vector service into a multi-surface backend that now owns:
The branch is large because it combines feature delivery with a substantial internal re-layout. The biggest review question is not any one handler. It is whether the new package boundaries, auth model, data model, and route surface still line up cleanly with the CALYPR frontend and deployment stack.
Scope by Area
git diff --dirstatagainstmainshows the branch is concentrated in these areas:internal/git/~10%internal/server/http/git/~9%internal/server/middleware/~8%gecko/legacy removal/replacement ~8%internal/server/http/config/~7%internal/db/~6%config/~5%internal/thumbnail/~5%tests/integration/~4%That matches the real shape of the work: this is mostly a Git/project backend branch, plus the refactor needed to support it.
Architecture Reorganization
Before
The old service logic lived mostly in the top-level
gecko/package with mixed concerns:After
The branch moves Gecko toward a clearer package layout:
config/internal/db/internal/git/internal/integrations/fence/internal/integrations/github/go-githubinternal/server/http/configdirectorygithealthvectorsharedinternal/server/middleware/internal/thumbnail/internal/httputil/internal/logging/internal/vectoradapter/This is the right direction structurally. The tradeoff is that the branch mixes architectural reorganization with product behavior changes, so code review needs to separate “moved” from “changed.”
Runtime / Bootstrap Changes
main.gonow builds Gecko as a composable server with optional integrations:The important runtime additions are:
--git-data-dir/GIT_DATA_DIR--fence-base-url/FENCE_BASE_URL--github-api-base-url/GITHUB_API_BASE_URLOnce DB connectivity is available, Gecko now also constructs:
git.NewGitService(...)thumbnail.NewFilesystemStore(gitDataDir)That makes
gitDataDira hard runtime dependency for the Git-enabled server path.CI impact
Because Gecko now requires a Git data directory, CI had to be updated. The branch modifies:
.github/workflows/tests.yamlto launch Gecko with:
Without that, the service exits before health checks come up.
Config Model Changes
Project config becomes first-class
This branch adds a typed
ProjectConfigmodel in:config/projectConfig.goSupported fields:
titlecontact_emailsrc_repoorg_titledescriptionproject_titleValidation includes:
host/owner/repoformThis is a real shift from using generic config blobs everywhere. Project metadata now has a stronger contract and normalization behavior.
Explorer config compatibility
This branch also carries forward explorer config compatibility work, including the richer
fileActionsshape:{ "extensions": {"ext": ["action"]}, "actions": {"action": "/path"} }That matters because the frontend expects this richer form, and Gecko has to unmarshal it correctly for CALYPR configs to load.
Database / Persistence Changes
The database layer is no longer only about simple
config_schema.<type>JSON tables.Existing typed config tables
The init path now ensures config tables for:
explorernavfile_summaryprojectprojectsNew Git-related state tables
internal/db/EnsureGitProjectStateTableexpands the DB footprint significantly. This branch adds persistence for:config_schema.git_project_stateconfig_schema.git_organization_stateconfig_schema.git_upload_sessionconfig_schema.git_upload_session_fileconfig_schema.git_pending_repositoryconfig_schema.git_setup_sessionThis is one of the biggest branch changes. Gecko is no longer stateless around Git operations; it is now persisting lifecycle and reconciliation state explicitly.
HTTP Surface Changes
The route surface is much broader than before.
Top-level registration
The new entrypoint is:
internal/server/http/register.goRegistered route families:
/health/Dir.../config.../git...Config routes
internal/server/http/config/register.gonow exposes:Generic config routes
GET /config/typesGET /config/listTyped config groups:
/config/explorer/config/nav/config/file_summary/config/projectPer-type operations include combinations of:
GET /listGET /:configIdPUT /:configIdDELETE /:configIdProject config routes
This branch adds a dedicated project config surface:
GET /config/projectsGET /config/projects/listGET /config/projects/summaryGET /config/projects/:orgTitle/:projectTitlePUT /config/projects/:orgTitle/:projectTitleDELETE /config/projects/:orgTitle/:projectTitleDELETE /config/projects/:orgTitleThis is materially different from the old “config row by arbitrary key” model. The route shape now matches organization/project semantics directly.
Git routes
internal/server/http/git/register.gois one of the largest new route families in the service.Organization-level Git routes
GET /git/projectsGET /git/organizations/statusPOST /git/organizations/reconcilePOST /git/organizations/:orgTitle/init-connectPOST /git/organizations/:orgTitle/connectGET /git/organizations/:orgTitle/statusPOST /git/organizations/:orgTitle/reconcileThese routes cover installation status, connect flows, and organization-wide repository reconciliation.
Project-level Git read routes
GET /git/projects/:orgTitle/:projectTitleGET /git/projects/:orgTitle/:projectTitle/refsGET /git/projects/:orgTitle/:projectTitle/treeGET /git/projects/:orgTitle/:projectTitle/tree/*GET /git/projects/:orgTitle/:projectTitle/file/*GET /git/projects/:orgTitle/:projectTitle/download/*GET /git/projects/:orgTitle/:projectTitle/thumbnailThese expose Gecko as a repository-backed project read service, not just a config API.
Project-level Git write/workflow routes
PUT /git/projects/:orgTitle/:projectTitle/setupPUT /git/projects/:orgTitle/:projectTitle/storagePUT /git/projects/:orgTitle/:projectTitle/thumbnailDELETE /git/projects/:orgTitle/:projectTitle/thumbnailPOST /git/projects/:orgTitle/:projectTitle/updatePOST /git/projects/:orgTitle/:projectTitle/uploads/sessionGET /git/projects/:orgTitle/:projectTitle/uploads/session/:sessionIDPOST /git/projects/:orgTitle/:projectTitle/uploads/session/:sessionID/filesPOST /git/projects/:orgTitle/:projectTitle/uploads/session/:sessionID/finalizeThis is a major expansion of product surface. Gecko is now responsible for project repository setup, update, artifact flow staging, and PR-style finalization.
Auth and Access Model
The middleware layer has been significantly expanded.
Resource path model
The branch standardizes project authorization around Arborist-style paths:
Helper functions in
internal/server/middleware/access.gonormalize and check these resource paths.Config auth model
ConfigAuthnow treats explorer configs differently from base/global config routes:Project config auth model
ProjectConfigAuthchecks direct access on:and also allows certain broader admin-like resource paths such as:
*/programs/programs/{org}/programs/{org}/projectsGit auth model
Git reads and organization reads are protected separately:
GitProjectAuthGitOrganizationAuthThe important boundary in this branch is:
Authorizationtoken and Arborist/Fence checksThat split is correct, but reviewers should confirm it stays consistent across all write routes.
Fence / GitHub Integration Model
This branch adds explicit integration clients instead of spreading ad hoc HTTP logic through handlers.
Fence integration
internal/integrations/fence/client.goturns Fence into a GitHub App broker that Gecko calls for:The request target is:
POST {FENCE_BASE_URL}/credentials/githubwith action-based payloads.
This is architecturally important. Gecko is moving away from owning GitHub App secrets directly and toward asking Fence for short-lived GitHub access on demand.
GitHub integration
internal/integrations/github/client.gouses:github.com/google/go-github/v87/githubfor GitHub API metadata reads.
At minimum, it currently centralizes repository metadata lookup:
This is the right direction and avoids more hand-written GitHub REST client code.
Git Service and Repository Semantics
The branch adds a large
internal/git/package that now owns:The key product shift is that Gecko is no longer just proxying config or metadata. It now maintains local repository state under a configured data directory and serves project Git views from there.
Reviewers should pay special attention to:
updatebehaves when the local repo is missing vs already presentUpload and Thumbnail Workflows
Two entirely new concerns land in this branch.
Upload sessions
Upload state is now explicit and persistent:
This means Gecko now participates in a staged contribution workflow rather than just reading repository state.
Thumbnails
internal/thumbnail/adds filesystem-backed thumbnail storage plus validation.Route support includes:
GET /git/projects/:orgTitle/:projectTitle/thumbnailPUT /git/projects/:orgTitle/:projectTitle/thumbnailDELETE /git/projects/:orgTitle/:projectTitle/thumbnailThat is a durable product-surface change and should be reviewed as such, not as a minor helper addition.
Legacy Code Removal
A large part of the diff is deletion of the old flat handlers from
gecko/, including legacy files such as:handleConfig.gohandleDir.gohandleVector.gomiddleware.goresponse.goserver.goThis is not dead-code cleanup alone. These deletions are paired with replacements under
internal/server/http/...,internal/server/middleware/..., and supporting packages.Build / Tooling Changes
This branch also touches:
DockerfileMakefile.dockerignorego.modgo.sumThose are not side noise. They are part of the fallout from:
Review should include a sanity pass on container build assumptions and root
go build .behavior.Testing Changes
The branch adds or updates tests across multiple layers:
Notable files include:
config/explorerConfig_test.goconfig/projectConfig_test.gointernal/git/service_test.gointernal/git/upload_test.gointernal/integrations/fence/client_test.gointernal/server/middleware/git_test.gointernal/thumbnail/store_test.gotests/integration/*Given the branch size, the main review question is coverage shape rather than raw test count:
Highest-Risk Areas
If reviewing this branch for merge readiness, focus here first:
Auth correctness
Route compatibility
DB/state lifecycle
Git/Fence boundary
Config schema compatibility
Startup behavior
git-data-dirBottom Line
This branch should be read as a backend expansion and service re-platforming branch, not as a narrow project-config feature.
The durable outcomes are: